﻿# -*- coding: utf-8 -*-
'''
Created on 25.05.2011

@author: Andrey Gaidel
'''

import committee
import forms
import models
import settings
import sql
from decimal import Decimal
from django.contrib import admin
from django import http
from django.shortcuts import render_to_response

SESSION_SCHOLARSHIP = "scholarship"
SESSION_WELFARE = "welfare"
SESSION_ERRORS = "errors"
SESSION_MESSAGE = "message"

class Action(object):
    pass

class DistributeScholarshipAction(Action):
    
    model_permission = "distribute_scholarship"
    permission = "dummy.distribute_scholarship"
    url = r"distribute"
    model = models.Scholarship
    verbose_name = u"Назначить стипендии"
    
    def done(self, request, extra_context):
        scholars = request.session.get(SESSION_SCHOLARSHIP, {})
        total = Decimal('0.0')
        if len(scholars) == 0:
            request.session[SESSION_MESSAGE] = u"Стипендия никому не выдана"
            return http.HttpResponseRedirect("../")
        scholars_view = [[{"name": u"Студент", "href": None},
                {"name": u"Группа", "href": None},
                {"name": u"Стипендия", "href": None},
                {"name": u"Выплачивается, месяцев", "href": None},
        ]]
        result = {}
        for scholar in scholars:
            if SESSION_ERRORS in scholars[scholar]:
                request.session[SESSION_MESSAGE] = u"Не все ошибки исправлены"
                return http.HttpResponseRedirect("../")
            payment = committee.total_payment(scholars[scholar])
            monthes = committee.monthes_till_next_session(scholar)
            total = total + payment * Decimal(repr(monthes))
            if payment <= Decimal('0.0'):
                request.session[SESSION_MESSAGE] = u"Не все ошибки исправлены"
                return http.HttpResponseRedirect("../")
            scholars_view.append([
                {"name": unicode(scholar), "href": None},
                {"name": unicode(scholar.group), "href": None},
                {"name": unicode(payment), "href": None},
                {"name": unicode(monthes), "href": None},
            ])
            result[scholar] = payment * Decimal(repr(monthes))
        scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[0]["name"])
        scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[1]["name"])
        scholars_view.append([
            {"name": unicode(u"ИТОГО"), "href": None},
            {"name": " ", "href": None},
            {"name": unicode(total), "href": None},
            {"name": " ", "href": None},
        ])
        fond = models.get_by_raw_SQL(models.SSF, sql.LAST_SSF, ())
        if len(fond) == 0:
            fond = Decimal('0.0')
        else:
            fond = fond[0].money
        if total > fond * Decimal('0.75'):
            request.session[SESSION_MESSAGE] = u"Не все ошибки исправлены"
            return http.HttpResponseRedirect("../")
        committee.give_scholarship(result)
        if SESSION_SCHOLARSHIP in request.session:
            del request.session[SESSION_SCHOLARSHIP]
        extra_context.update({
            "app_label": DistributeScholarshipAction.model._meta.app_label,
            "model_name": DistributeScholarshipAction.model._meta.verbose_name,
            "model_name_plural": DistributeScholarshipAction.model._meta.verbose_name_plural,
            "title": u"Стипендии выданы",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "action_name": DistributeScholarshipAction.verbose_name
        })
        return render_to_response("scholarship_done.html", extra_context)
    
    def edit(self, request, extra_context, student):
        scholars = request.session.get(SESSION_SCHOLARSHIP, {})
        if student not in scholars:
            raise http.Http404()
        scholarship = scholars[student]
        if request.method == "POST":
            form = forms.PaymentForm(request.POST)
            if form.is_valid():
                scholars[student][None] = form.cleaned_data["payment"]
                request.session[SESSION_SCHOLARSHIP] = scholars
                return http.HttpResponseRedirect("../../")
        else:
            form = forms.PaymentForm({"payment": scholarship.get(None, Decimal('0.0'))})
        scholars_view = None
        pretenders_view = None
        studentclass_modeladmin = admin.site._registry[models.StudentClass]
        classes = [clazz for clazz in scholarship if clazz != SESSION_ERRORS and clazz is not None]
        classes.sort(key=lambda x: x.name)
        scholars_view = [[{"name": u"Категория", "href": None},
                {"name": u"Выплата", "href": None},
                {"name": u"Действия", "href": None}]]
        for clazz in classes:
            href = None
            if studentclass_modeladmin.has_view_permission(request, clazz) or studentclass_modeladmin.has_change_permission(request, clazz):
                href = "../../../../studentclass/%s/" % clazz.pk
            scholars_view.append([{"name": unicode(clazz), "href": href},
                    {"name": unicode(scholarship[clazz]), "href": None},
                    {"name": u"Убрать", "href": "%s/" % clazz.pk}])
        pretenders = []
        for clazz in student.stud_classes.all():
            if clazz not in classes and clazz.coefficient > Decimal('0.0'):
                pretenders.append(clazz)
        if len(pretenders) > 0:
            pretenders_view = [[{"name": u"Категория", "href": None},
                    {"name": u"Выплата", "href": None},
                    {"name": u"Действия", "href": None}]]
            for clazz in pretenders:
                href = None
                if studentclass_modeladmin.has_view_permission(request, clazz) or studentclass_modeladmin.has_change_permission(request, clazz):
                    href = "../../../../studentclass/%s/" % clazz.pk
                pretenders_view.append([{"name": unicode(clazz), "href": href},
                        {"name": committee.calc_scholarship_payment(clazz), "href": None},
                        {"name": u"Добавить", "href": "%s/" % clazz.pk}])
        extra_context.update({
            "app_label": DistributeScholarshipAction.model._meta.app_label,
            "model_name": DistributeScholarshipAction.model._meta.verbose_name,
            "model_name_plural": DistributeScholarshipAction.model._meta.verbose_name_plural,
            "action_name": DistributeScholarshipAction.verbose_name,
            "title": u"Выплаты по категориям",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "pretenders": pretenders_view,
            "form": form,
        })
        return render_to_response("edit_classes.html", extra_context)
    
    def process(self, request, extra_context):
        if SESSION_MESSAGE in request.session:
            message = request.session[SESSION_MESSAGE]
            del request.session[SESSION_MESSAGE]
        else:
            message = None
        scholars = request.session.get(SESSION_SCHOLARSHIP, {})
        scholars_view = None
        pretenders_view = None
        pretenders = get_scholarship_pretenders(request)
        student_model_admin = admin.site._registry[models.Student]
        group_model_admin = admin.site._registry[models.StudentGroup]
        total = Decimal('0.0')
        if len(scholars) > 0:
            scholars_view = [[{"name": u"Студент", "href": None},
                    {"name": u"Группа", "href": None},
                    {"name": u"Стипендия", "href": None},
                    {"name": u"Выплачивается месяцев", "href": None},
                    {"name": u"Действия", "href": None}]]
            for scholar in scholars:
                if scholar in pretenders:
                    del pretenders[scholar]
                stud_href = None
                group_href = None
                errors = None
                payment = committee.total_payment(scholars[scholar])
                monthes = committee.monthes_till_next_session(scholar)
                total = total + payment * Decimal(repr(monthes))
                if payment <= Decimal('0.0') and SESSION_ERRORS not in scholars[scholar]:
                    scholars[scholar][SESSION_ERRORS] = u"Выплата должна быть положительной"
                if student_model_admin.has_view_permission(request, scholar) or student_model_admin.has_change_permission(request, scholar):
                    stud_href = "../../student/%s/" % scholar.pk
                if group_model_admin.has_view_permission(request, scholar.group) or group_model_admin.has_change_permission(request, scholar.group):
                    group_href = "../../studentgroup/%s/" % scholar.group.pk
                if SESSION_ERRORS in scholars[scholar]:
                    errors = scholars[scholar][SESSION_ERRORS]
                scholars_view.append([
                    {"name": unicode(scholar), "href": stud_href, SESSION_ERRORS: errors},
                    {"name": unicode(scholar.group), "href": group_href},
                    {"name": unicode(payment), "href": "edit/%s/" % scholar.pk},
                    {"name": unicode(monthes), "href": None},
                    {"name": u"Убрать", "href": "delete/%s/" % scholar.pk},
                ])
            scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[0]["name"])
            scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[1]["name"])
            scholars_view.append([
                    {"name": unicode(u"ИТОГО"), "href": None},
                    {"name": " ", "href": None},
                    {"name": unicode(total), "href": None},
                    {"name": " ", "href": None},
                    {"name": " ", "href": None},
                ])
        if len(pretenders) > 0:
            pretenders_view = [[{"name": u"Студент", "href": None},
                    {"name": u"Группа", "href": None},
                    {"name": u"Предполагаемая стипендия", "href": None},
                    {"name": u"Действия", "href": None}]]
            for pretender in pretenders:
                stud_href = None
                group_href = None
                if student_model_admin.has_view_permission(request, pretender) or student_model_admin.has_change_permission(request, pretender):
                    stud_href = "../../student/%s/" % pretender.pk
                if group_model_admin.has_view_permission(request, pretender.group) or group_model_admin.has_change_permission(request, pretender.group):
                    group_href = "../../studentgroup/%s/" % pretender.group.pk
                pretenders_view.append([
                    {"name": unicode(pretender), "href": stud_href},
                    {"name": unicode(pretender.group), "href": group_href},
                    {"name": unicode(committee.total_payment(pretenders[pretender])), "href": None},
                    {"name": u"Добавить", "href": "%s/" % pretender.pk},
                ])
            pretenders_view[1:] = sorted(pretenders_view[1:], key=lambda x: x[0]["name"])
            pretenders_view[1:] = sorted(pretenders_view[1:], key=lambda x: x[1]["name"])
        fond = models.get_by_raw_SQL(models.SSF, sql.LAST_SSF, ())
        if len(fond) == 0:
            fond = Decimal('0.0')
        else:
            fond = fond[0].money
        errors = None
        if total > fond * Decimal('0.75'):
            errors = u"Израсходовано более 75% Фонда Социальной Защиты!"
        extra_context.update({
            "app_label": DistributeScholarshipAction.model._meta.app_label,
            "model_name": DistributeScholarshipAction.model._meta.verbose_name,
            "model_name_plural": DistributeScholarshipAction.model._meta.verbose_name_plural,
            "title": DistributeScholarshipAction.verbose_name,
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "pretenders": pretenders_view,
            "fond": fond,
            "rest": fond - total,
            "errors": errors,
            "message": message
        })
        return render_to_response("distribute_scholarship.html", extra_context)

class DistributeWelfareAction(Action):
    
    model_permission = "distribute_welfare"
    permission = "dummy.distribute_welfare"
    url = r"distribute"
    model = models.Welfare
    verbose_name = u"Назначить разовые социальные пособия"
    
    def done(self, request, scholars, total, date):
        result = {}
        requests = {}
        scholars_view = [[{"name": u"Студент", "href": None},
                {"name": u"Группа", "href": None},
                {"name": u"Пособие", "href": None}]]
        for scholar in scholars:
            payment = committee.total_payment(scholars[scholar])
            req = None
            for clazz in scholars[scholar]:
                if type(clazz) == models.WelfareRequest:
                    req = clazz
                    break
            if req is not None:
                requests[scholar] = req
            result[scholar] = payment
            scholars_view.append([
                {"name": unicode(scholar), "href": None},
                {"name": unicode(scholar.group), "href": None},
                {"name": unicode(payment), "href": None},
            ])
        scholars_view.append([
            {"name": unicode(u"ИТОГО"), "href": None},
            {"name": " ", "href": None},
            {"name": unicode(total), "href": None},
        ])
        committee.give_welfare(result, requests, date)
        if SESSION_WELFARE in request.session:
            del request.session[SESSION_WELFARE]
        extra_context = {
            "app_label": DistributeWelfareAction.model._meta.app_label,
            "model_name": DistributeWelfareAction.model._meta.verbose_name,
            "model_name_plural": DistributeWelfareAction.model._meta.verbose_name_plural,
            "title": u"Социальные пособия выданы",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "action_name": DistributeWelfareAction.verbose_name,
            "date": date,
        }
        return render_to_response("welfare_done.html", extra_context)
    
    def edit(self, request, extra_context, student):
        scholars = request.session.get(SESSION_WELFARE, {})
        if student not in scholars:
            raise http.Http404()
        welfare = scholars[student]
        if request.method == "POST":
            form = forms.PaymentForm(request.POST)
            if form.is_valid():
                scholars[student][None] = form.cleaned_data["payment"]
                request.session[SESSION_WELFARE] = scholars
                return http.HttpResponseRedirect("../../")
        else:
            form = forms.PaymentForm({"payment": welfare.get(None, Decimal('0.0'))})
        scholars_view = None
        pretenders_view = None
        studentclass_modeladmin = admin.site._registry[models.StudentClass]
        welfarerequest_modeladmin = admin.site._registry[models.WelfareRequest]
        classes = [clazz for clazz in welfare if clazz != SESSION_ERRORS and clazz is not None and type(clazz) != models.WelfareRequest]
        requests = [clazz for clazz in welfare if type(clazz) == models.WelfareRequest]
        classes.sort(key=lambda x: x.name)
        requests.sort(key=lambda x: x.date)
        scholars_view = [[{"name": u"Категория", "href": None},
                {"name": u"Выплата", "href": None},
                {"name": u"Действия", "href": None}]]
        for clazz in classes:
            href = None
            if studentclass_modeladmin.has_view_permission(request, clazz) or studentclass_modeladmin.has_change_permission(request, clazz):
                href = "../../../../studentclass/%s/" % clazz.pk
            scholars_view.append([{"name": unicode(clazz), "href": href},
                    {"name": unicode(welfare[clazz]), "href": None},
                    {"name": u"Убрать", "href": "%s/" % clazz.pk}])
        for req in requests:
            href = None
            if welfarerequest_modeladmin.has_view_permission(request, req) or welfarerequest_modeladmin.has_change_permission(request, req):
                href = "../../../../welfarerequest/%s/" % req.pk
            scholars_view.append([{"name": u"Запрос на материальную помощь от %s" % unicode(req.date), "href": href},
                    {"name": unicode(req.cash), "href": None},
                    {"name": u"Убрать", "href": "request/%s/" % req.pk}])
        pretenders = []
        for clazz in student.stud_classes.all():
            if clazz not in classes and clazz.payment > Decimal('0.0'):
                pretenders.append(clazz)
        req = models.get_by_raw_SQL(models.WelfareRequest, sql.LAST_REQUEST, (student.pk,))
        if len(req) != 0 and req[0] not in requests:
            req = req[0]
        else:
            req = None
        if len(pretenders) > 0 or req is not None:
            pretenders_view = [[{"name": u"Категория", "href": None},
                    {"name": u"Выплата", "href": None},
                    {"name": u"Действия", "href": None}]]
            for clazz in pretenders:
                href = None
                if studentclass_modeladmin.has_view_permission(request, clazz) or studentclass_modeladmin.has_change_permission(request, clazz):
                    href = "../../../../studentclass/%s/" % clazz.pk
                pretenders_view.append([{"name": unicode(clazz), "href": href},
                        {"name": unicode(clazz.payment), "href": None},
                        {"name": u"Добавить", "href": "%s/" % clazz.pk}])
            if req is not None:
                href = None
                if welfarerequest_modeladmin.has_view_permission(request, req) or welfarerequest_modeladmin.has_change_permission(request, req):
                    href = "../../../../welfarerequest/%s/" % req.pk
                pretenders_view.append([{"name": u"Запрос на материальную помощь от %s" % unicode(req.date), "href": href},
                        {"name": unicode(req.cash), "href": None},
                        {"name": u"Добавить", "href": "request/%s/" % req.pk}])
        extra_context.update({
            "app_label": DistributeWelfareAction.model._meta.app_label,
            "model_name": DistributeWelfareAction.model._meta.verbose_name,
            "model_name_plural": DistributeWelfareAction.model._meta.verbose_name_plural,
            "action_name": DistributeWelfareAction.verbose_name,
            "title": u"Выплаты по категориям",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "pretenders": pretenders_view,
            "form": form,
        })
        return render_to_response("edit_classes.html", extra_context)
    
    def process(self, request, extra_context):
        if SESSION_MESSAGE in request.session:
            message = request.session[SESSION_MESSAGE]
            del request.session[SESSION_MESSAGE]
        else:
            message = None
        err = False
        scholars = request.session.get(SESSION_WELFARE, {})
        scholars_view = None
        pretenders_view = None
        pretenders = get_welfare_all_students(request)
        student_model_admin = admin.site._registry[models.Student]
        group_model_admin = admin.site._registry[models.StudentGroup]
        total = Decimal('0.0')
        if len(scholars) > 0:
            scholars_view = [[{"name": u"Студент", "href": None},
                    {"name": u"Группа", "href": None},
                    {"name": u"Пособие", "href": None},
                    {"name": u"Действия", "href": None}]]
            for scholar in scholars:
                if scholar in pretenders:
                    del pretenders[scholar]
                stud_href = None
                group_href = None
                errors = None
                payment = committee.total_payment(scholars[scholar])
                total = total + payment
                if payment <= Decimal('0.0') and SESSION_ERRORS not in scholars[scholar]:
                    scholars[scholar][SESSION_ERRORS] = u"Выплата должна быть положительной"
                    err = True
                reqs = sum([1 for req in scholars[scholar] if type(req) == models.WelfareRequest])
                if reqs > 1 and SESSION_ERRORS not in scholars[scholar]:
                    scholars[scholar][SESSION_ERRORS] = u"Можно выдать пособие только по одному заявлению"
                    err = True
                if student_model_admin.has_view_permission(request, scholar) or student_model_admin.has_change_permission(request, scholar):
                    stud_href = "../../student/%s/" % scholar.pk
                if group_model_admin.has_view_permission(request, scholar.group) or group_model_admin.has_change_permission(request, scholar.group):
                    group_href = "../../studentgroup/%s/" % scholar.group.pk
                if SESSION_ERRORS in scholars[scholar]:
                    errors = scholars[scholar][SESSION_ERRORS]
                    err = True
                scholars_view.append([
                    {"name": unicode(scholar), "href": stud_href, SESSION_ERRORS: errors},
                    {"name": unicode(scholar.group), "href": group_href},
                    {"name": unicode(payment), "href": "edit/%s/" % scholar.pk},
                    {"name": u"Убрать", "href": "delete/%s/" % scholar.pk},
                ])
            scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[0]["name"])
            scholars_view[1:] = sorted(scholars_view[1:], key=lambda x: x[1]["name"])
            scholars_view.append([
                    {"name": unicode(u"ИТОГО"), "href": None},
                    {"name": " ", "href": None},
                    {"name": unicode(total), "href": None},
                    {"name": " ", "href": None},
                ])
        if len(pretenders) > 0:
            pretenders_view = [[{"name": u"Студент", "href": None},
                    {"name": u"Группа", "href": None},
                    {"name": u"Предполагаемое пособие", "href": None},
                    {"name": u"Действия", "href": None}]]
            for pretender in pretenders:
                stud_href = None
                group_href = None
                if student_model_admin.has_view_permission(request, pretender) or student_model_admin.has_change_permission(request, pretender):
                    stud_href = "../../student/%s/" % pretender.pk
                if group_model_admin.has_view_permission(request, pretender.group) or group_model_admin.has_change_permission(request, pretender.group):
                    group_href = "../../studentgroup/%s/" % pretender.group.pk
                pretenders_view.append([
                    {"name": unicode(pretender), "href": stud_href},
                    {"name": unicode(pretender.group), "href": group_href},
                    {"name": unicode(committee.total_payment(pretenders[pretender])), "href": None},
                    {"name": u"Добавить", "href": "%s/" % pretender.pk},
                ])
            pretenders_view[1:] = sorted(pretenders_view[1:], key=lambda x: x[0]["name"])
            pretenders_view[1:] = sorted(pretenders_view[1:], key=lambda x: x[1]["name"])
        fond = models.get_by_raw_SQL(models.SSF, sql.LAST_SSF, ())
        if len(fond) == 0:
            fond = Decimal('0.0')
        else:
            fond = fond[0].money
        errors = None
        if total > fond * Decimal('0.25'):
            errors = u"Израсходовано более 25% Фонда Социальной Защиты!"
            err = True
        if request.method == "POST":
            form = forms.DateForm(request.POST)
            if form.is_valid():
                for scholar in scholars:
                    if models.Welfare.objects.filter(student=scholar, \
                            date__year=repr(form.cleaned_data["date"].year), \
                            date__month=repr(form.cleaned_data["date"].month)).count() > 0 \
                            and SESSION_ERRORS not in scholars[scholar]:
                        scholars[scholar][SESSION_ERRORS] = u"Этот студент уже получал социальное пособие в указанном месяце"
                        for line in scholars_view:
                            if line[0]["name"] == unicode(scholar):
                                line[0]["errors"] = scholars[scholar][SESSION_ERRORS]
                        err = True
                if err:
                    message = u"Не все ошибки исправлены"
                elif len(scholars) == 0:
                    message = u"Социальное пособие никому не выдано"
                else:
                    return self.done(request, scholars, total, form.cleaned_data["date"])
        else:
            form = forms.DateForm()
        extra_context.update({
            "app_label": DistributeWelfareAction.model._meta.app_label,
            "model_name": DistributeWelfareAction.model._meta.verbose_name,
            "model_name_plural": DistributeWelfareAction.model._meta.verbose_name_plural,
            "title": DistributeWelfareAction.verbose_name,
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "scholars": scholars_view,
            "pretenders": pretenders_view,
            "fond": fond,
            "rest": fond - total,
            "errors": errors,
            "message": message,
            "form": form,
        })
        return render_to_response("distribute_welfare.html", extra_context)

class ScholarshipBySemesterAction(Action):
    
    model_permission = "scholarship_by_semester"
    permission = "dummy.scholarship_by_semester"
    url = r"bysemester"
    model = models.Scholarship
    verbose_name = u"Просмотреть стипендии по семестрам"
    
    def process(self, request, extra_context):
        view = None
        if request.method == 'POST':
            form = forms.ScholarshipBySemesterForm(request.POST)
            if form.is_valid():
                year = int(form.cleaned_data['years'])
                num = int(form.cleaned_data['semester'])
                if num == 0:
                    year = year - 1
                scholarships = models.get_by_raw_SQL(models.Scholarship,
                        sql.SCHOLARSHIP_BY_SEMESTER, (str(year), str(year), str(num)))
                if len(scholarships) > 0:
                    student_model_admin = admin.site._registry[models.Student]
                    group_model_admin = admin.site._registry[models.StudentGroup]
                    scholarship_model_admin = admin.site._registry[models.Scholarship]
                    scholarships.sort(key=lambda x: unicode(x.student))
                    scholarships.sort(key=lambda x: unicode(x.student.group))
                    view = [[{"name": u"Студент", "href": None},
                        {"name": u"Группа", "href": None},
                        {"name": u"Размер стипендии", "href": None}]]
                    for scholarship in scholarships:
                        stud_href = None
                        group_href = None
                        scholarship_href = None
                        if student_model_admin.has_view_permission(request, scholarship.student) or student_model_admin.has_change_permission(request, scholarship.student):
                            stud_href = "../../student/%s/" % scholarship.student.pk
                        if group_model_admin.has_view_permission(request, scholarship.student.group) or group_model_admin.has_change_permission(request, scholarship.student.group):
                            group_href = "../../studentgroup/%s/" % scholarship.student.group.pk
                        if scholarship_model_admin.has_view_permission(request, scholarship) or scholarship_model_admin.has_change_permission(request, scholarship):
                            scholarship_href = "../%s/" % scholarship.pk
                        view.append([
                            {"name": unicode(scholarship.student), "href": stud_href},
                            {"name": unicode(scholarship.student.group), "href": group_href},
                            {"name": unicode(scholarship.cash.payment), "href": scholarship_href},
                        ])
        else:
            form = forms.ScholarshipBySemesterForm()
        extra_context.update({
            "app_label": ScholarshipBySemesterAction.model._meta.app_label,
            "form": form,
            "model_name": ScholarshipBySemesterAction.model._meta.verbose_name,
            "model_name_plural": ScholarshipBySemesterAction.model._meta.verbose_name_plural,
            "title": u"Выданные стипендии",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "view": view,
        })
        return render_to_response("scholarship_by_semester.html", extra_context)

class SendWelfareRequestAction(Action):
    
    model_permission = "send_request"
    permission = "dummy.send_request"
    url = r"send"
    model = models.WelfareRequest
    verbose_name = u"Написать заявление на материальную помощь"
    
    def process(self, request, extra_context):
        if request.method == 'POST':
            form = forms.SendRequestForm(request.POST)
            student = None
            try:
                student = models.Student.objects.get(user=request.user)
            except models.Student.DoesNotExist:
                form.errors['__all__'] = form.error_class([u"Вы не являетесь студентом."])
            if form.is_valid() and student is not None:
                instance = form.save(commit=False)
                instance.student = student
                instance.save()
                return http.HttpResponseRedirect("../")
        else:
            form = forms.SendRequestForm()
        extra_context.update({
            "app_label": SendWelfareRequestAction.model._meta.app_label,
            "form": form,
            "model_name": SendWelfareRequestAction.model._meta.verbose_name,
            "model_name_plural": SendWelfareRequestAction.model._meta.verbose_name_plural,
            "title": u"Оформить заявление на материальную помощь",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
        })
        return render_to_response("send_request.html", extra_context)

class SessionResultAction(Action):
    
    model_permission = "result_session"
    permission = "dummy.result_session"
    url = r"result"
    model = models.Session
    verbose_name = u"Просмотреть результаты сессии"
    
    def process(self, request, extra_context):
        form = forms.SessionResultForm(request.REQUEST)
        marks = None
        if form.is_valid():
            marks = models.get_by_raw_SQL(models.Mark, sql.SESSION_RESULTS,
                    [form.cleaned_data["session"].pk, form.cleaned_data["group"].pk])
        view = None
        if marks is not None and len(marks) > 0:
            table = {}
            students = set()
            examinations = set()
            for mark in marks:
                students.add(mark.student)
                examinations.add(mark.examination)
                if mark.student in table:
                    table[mark.student][mark.examination] = mark
                else:
                    table[mark.student] = {mark.examination: mark}
            students = list(students)
            examinations = list(examinations)
            students.sort(key=unicode)
            examinations.sort(key=unicode)
            href = None
            student_model_admin = admin.site._registry[models.Student]
            examination_model_admin = admin.site._registry[models.Examination]
            mark_model_admin = admin.site._registry[models.Mark]
            if student_model_admin.has_list_permission(request):
                href = u"../../student/"
            line = [{
               "name": models.Student._meta.verbose_name_plural,
               "href": href,
            }]
            for examination in examinations:
                href = None
                if examination_model_admin.has_view_permission(request, examination) or examination_model_admin.has_change_permission(request, examination):
                    href = u"../../examination/%s/" % examination.pk
                line.append({
                   "name": unicode(examination),
                   "href": href,
                })
            view = [line]
            for student in students:
                href = None
                if student_model_admin.has_view_permission(request, student) or student_model_admin.has_change_permission(request, student):
                    href = u"../../student/%s/" % student.pk
                line = [{
                   "name": unicode(student),
                   "href": href,
                }]
                for examination in examinations:
                    href = None
                    if examination in table[student]:
                        mark = table[student][examination]
                        if mark_model_admin.has_view_permission(request, mark) or mark_model_admin.has_change_permission(request, mark):
                            href = u"../../mark/%s/" % mark.pk
                        line.append({
                            "name": unicode(mark.grade),
                            "href": href
                        })
                    else:
                        line.append({
                            "name": u"Н/А",
                            "href": None
                        })
                view.append(line)
        if request.method == 'GET':
            form.errors.clear()
        extra_context.update({
            "app_label": SessionResultAction.model._meta.app_label,
            "form": form,
            "model_name": SessionResultAction.model._meta.verbose_name,
            "model_name_plural": SessionResultAction.model._meta.verbose_name_plural,
            "title": u"Результаты сессии",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
            "view": view,
        })
        return render_to_response("session_result.html", extra_context)

class StudentsByGroupAction(Action):
    
    model_permission = "students_by_group"
    permission = "dummy.students_by_group"
    url = r"bygroup"
    model = models.Student
    verbose_name = u"Просмотреть студентов по группам"
    
    def process(self, request, group_pk, extra_context):
        group = None
        students = []
        back = ""
        form = None
        if request.method == "POST":
            form = forms.StudentGroupChoiceForm(request.POST)
            if form.is_valid():
                url = str(form.cleaned_data["groups"].id) + "/"
                if group_pk is not None:
                    url = "../" + url
                return http.HttpResponseRedirect(url)
        if group_pk is not None:
            back = "../"
            try:
                group = models.StudentGroup.objects.get(pk=group_pk)
            except models.StudentGroup.DoesNotExist:
                raise http.Http404()
        if group is not None:
            students = models.get_by_raw_SQL(models.Student, sql.STUDENTS_BY_GROUP, [group.pk])
        studs = []
        for stud in students:
            studs.append({
                "id": stud.id,
                "name": unicode(stud),
                "has_perm": request.user.is_superuser or request.user.has_perm("dummy.view_student")
                        or request.user.has_perm("dummy.change_student")
            })
        if form is None:
            form = forms.StudentGroupChoiceForm(initial={"groups": group})
        extra_context.update({
            "app_label": StudentsByGroupAction.model._meta.app_label,
            "back": back,
            "form": form,
            "group": group,
            "model_name": StudentsByGroupAction.model._meta.verbose_name,
            "model_name_plural": StudentsByGroupAction.model._meta.verbose_name_plural,
            "students": studs,
            "title": u"Список студентов по группе",
            "user": request.user,
            "admin_media_prefix": settings.ADMIN_MEDIA_PREFIX,
        })
        return render_to_response("students_by_group.html", extra_context)

def get_permissions(user):
    ans = {}
    for sub in Action.__subclasses__():
        ans.update({sub.model_permission: user.is_superuser or user.has_perm(sub.permission)})
    return ans

def get_actions(user):
    ans = []
    for sub in Action.__subclasses__():
        if user.is_superuser or user.has_perm(sub.permission):
            ans.append({
                'model': sub.model,
                'url': sub.url,
                'verbose_name': sub.verbose_name,
            })
    ans.sort(key=lambda x: x['verbose_name'])
    return ans

def add_error(scholarship, student, message):
    if scholarship is None:
        scholarship = {}
    if student in scholarship:
        scholarship[student][SESSION_ERRORS] = message
    else:
        scholarship[student] = {SESSION_ERRORS: message}

def check_faculty(request, student):
    try:
        faculty = models.Committee.objects.get(user=request.user).faculty
    except:
        return True
    return faculty == student.group.speciality.faculty

def distribute_scholarship(modeladmin, request, queryset):
    if modeladmin.model == models.Student:
        return add_scholarship_students(modeladmin, request, queryset)
    elif modeladmin.model == models.StudentClass:
        return add_scholarship_classes(modeladmin, request, queryset)
    else:
        modeladmin.message_user(request, u"Данное действие не предусмотрено в рамках модели %s" % modeladmin.opts.verbose_name)

distribute_scholarship.short_description = DistributeScholarshipAction.verbose_name
distribute_scholarship.permission = DistributeScholarshipAction.permission

def distribute_welfare(modeladmin, request, queryset):
    if modeladmin.model == models.Student:
        return add_welfare_students(modeladmin, request, queryset)
    elif modeladmin.model == models.StudentClass:
        return add_welfare_classes(modeladmin, request, queryset)
    elif modeladmin.model == models.WelfareRequest:
        return add_welfare_requests(modeladmin, request, queryset)
    else:
        modeladmin.message_user(request, u"Данное действие не предусмотрено в рамках модели %s" % modeladmin.opts.verbose_name)

distribute_welfare.short_description = DistributeWelfareAction.verbose_name
distribute_welfare.permission = DistributeWelfareAction.permission

def get_scholarship_all_students(request):
    ans = {}
    for student in list(models.Student.objects.all()):
        if not check_faculty(request, student):
            continue
        try:
            plan = committee.calc_scholarship(student)
            if committee.total_payment(plan) > Decimal('0.0'):
                ans[student] = plan
        except committee.CommitteeException:
            pass
    return ans

def get_scholarship_pretenders(request):
    ans = {}
    for student in list(models.Student.objects.all()):
        if not check_faculty(request, student):
            continue
        try:
            plan = committee.calc_scholarship(student)
            maybe = False
            for clazz in student.stud_classes.all():
                if clazz.coefficient > Decimal('0.0'):
                    maybe = True
                    break
            if committee.total_payment(plan) > Decimal('0.0') or maybe:
                ans[student] = plan
        except committee.CommitteeException:
            pass
    return ans

def add_scholarship_students(modeladmin, request, queryset):
    scholarship = request.session.get(SESSION_SCHOLARSHIP, {})
    for student in queryset.all():
        if not check_faculty(request, student):
            add_error(scholarship, student, u"Вы не имеете права выдавать стипендию студентам на факультете %s" % student.group.speciality.faculty)
            continue
        try:
            scholarship[student] = committee.calc_scholarship(student)
        except committee.CommitteeException as ex:
            add_error(scholarship, student, ex.message)
    request.session[SESSION_SCHOLARSHIP] = scholarship
    return http.HttpResponseRedirect("../scholarship/%s/" % DistributeScholarshipAction.url)

def add_scholarship_classes(modeladmin, request, queryset):
    scholarship = request.session.get(SESSION_SCHOLARSHIP, {})
    classes = list(queryset.all())
    students = []
    for student in models.Student.objects.all():
        if not check_faculty(request, student):
            continue
        for clazz in classes:
            if student.stud_classes.filter(pk=clazz.pk).count() > 0:
                students.append(student)
                break
    for student in students:
        if student in scholarship:
            continue
        try:
            scholarship[student] = committee.calc_scholarship(student)
            for clazz0 in student.stud_classes.all():
                for clazz1 in queryset.all():
                    if clazz0 == clazz1 and clazz0.coefficient > Decimal('0.0') and clazz0 not in scholarship[student]:
                        scholarship[student][clazz0] = committee.calc_scholarship_payment(clazz0)
                        break
        except committee.CommitteeException:
            pass
    request.session[SESSION_SCHOLARSHIP] = scholarship
    if len(scholarship) == 0:
        modeladmin.message_user(request, u"По выбранным категориям стипендии отсутствуют")
    else:
        return http.HttpResponseRedirect("../scholarship/%s/" % DistributeScholarshipAction.url)

def get_welfare_all_students(request):
    ans = {}
    for student in list(models.Student.objects.all()):
        if not check_faculty(request, student):
            continue
        try:
            plan = committee.calc_welfare(student)
            if committee.total_payment(plan) > Decimal('0.0'):
                ans[student] = plan
        except committee.CommitteeException:
            pass
    return ans

def add_welfare_students(modeladmin, request, queryset):
    welfare = request.session.get(SESSION_WELFARE, {})
    for student in queryset.all():
        if not check_faculty(request, student):
            add_error(welfare, student, u"Вы не имеете права выдавать социальные пособия студентам на факультете %s" % student.group.speciality.faculty)
            continue
        try:
            welfare[student] = committee.calc_welfare(student)
        except committee.CommitteeException as ex:
            add_error(welfare, student, ex.message)
    request.session[SESSION_WELFARE] = welfare
    return http.HttpResponseRedirect("../welfare/%s/" % DistributeWelfareAction.url)

def add_welfare_classes(modeladmin, request, queryset):
    welfare = request.session.get(SESSION_WELFARE, {})
    for clazz in queryset.all():
        for student in models.Student.objects.all():
            if not check_faculty(request, student):
                continue
            restriction = False
            for stud_class in student.stud_classes.all():
                if stud_class.restriction:
                    restriction = True
                    break
            if restriction:
                continue
            for stud_class in student.stud_classes.all():
                if stud_class == clazz:
                    if student in welfare:
                        if clazz not in welfare[student]:
                            welfare[student][clazz] = clazz.payment
                    else:
                        welfare[student] = {clazz: clazz.payment}
    request.session[SESSION_WELFARE] = welfare
    if len(welfare) == 0:
        modeladmin.message_user(request, u"По выбранным категориям социальные пособия отсутствуют")
    else:
        return http.HttpResponseRedirect("../welfare/%s/" % DistributeWelfareAction.url)

def add_welfare_requests(modeladmin, request, queryset):
    welfare = request.session.get(SESSION_WELFARE, {})
    for req in queryset.all():
        if req.student not in welfare:
            welfare[req.student] = {}
        for stud_class in req.student.stud_classes.all():
            if stud_class.restriction:
                welfare[req.student][SESSION_ERRORS] = u"Этот студент относится к категории %s, которая не допускает выдачу социальных пособий" % unicode(stud_class)
        if not committee.check_request(req):
            welfare[req.student][SESSION_ERRORS] = u"По данному заявлению социальное пособие уже выдано"
        welfare[req.student][req] = req.cash
    request.session[SESSION_WELFARE] = welfare
    return http.HttpResponseRedirect("../welfare/%s/" % DistributeWelfareAction.url)
